package eventbus

import (
	"go-iot/app/iot/eventbus/matcher"
	"go-iot/app/iot/eventbus/message"
	"reflect"
	"sync"
)

// event bus of single node
type SingleNodeEventBus struct {
	sync.Mutex
	data    map[string][]func(data message.Message)
	matcher matcher.AntPathMatcher
}

func (eventBus *SingleNodeEventBus) match(pattern string, path string) bool {
	return eventBus.matcher.Match(pattern, path)
}

func (eventBus *SingleNodeEventBus) Subscribe(pattern string, run func(msg message.Message)) {
	eventBus.Lock()
	defer eventBus.Unlock()
	eventBus.data[pattern] = append(eventBus.data[pattern], run)
}

func (eventBus *SingleNodeEventBus) UnSubscribe(pattern string, run func(data message.Message)) {
	eventBus.Lock()
	defer eventBus.Unlock()
	listener := eventBus.data[pattern]
	var l1 []func(data message.Message)
	for _, callback := range listener {
		sf1 := reflect.ValueOf(callback)
		sf2 := reflect.ValueOf(run)
		if sf1.Pointer() != sf2.Pointer() {
			l1 = append(l1, callback)
		}
	}
	eventBus.data[pattern] = l1
}

func (eventBus *SingleNodeEventBus) publish(topic string, data message.Message) {
	eventBus.Lock()
	defer eventBus.Unlock()
	for pattern, listener := range eventBus.data {
		if eventBus.match(pattern, topic) {
			for _, callback := range listener {
				go callback(data)
			}
		}
	}
}
